package main

import (
	"fmt"
	"strconv"
	"time"
)

/**
程序(program)：是为了完成特定任务，用某种语言编写的一组指令的集合，是一段静态的代码。程序是静态的
进程(process):是程序的一次执行过程，正在运行的一个程序，进程作为资源分配的单位，在内存中为每个进程分配不同的内存区域，进程是动态的，进程的生命周期：有它自身的产生存在和消亡的过程
线程(thread):进程可进一步细化为线程，是一个程序内部的一条执行路径，若一个进程同时执行多个线程，就是支持多线程的
协程(goroutine)又称为微线程，协程，是一种用户态的轻量级线程
协程的作用:
在执行A函数的时候，可以随时中断，去执行B函数，然后中断继续执行A函数(可以自动切换)，注意这一切换并不是函数的调用(没有调用语句)，过程很像单线程，然而协程只有一个线程在执行
协程的本质就是单线程
对于单线程下，我们不可避免程序中出现io操作，但如果我们能够在自己的程序中控制单线程下的多个任务能在一个任务中遇到io阻塞时就将寄存器上下文和栈保存到某个地方，然后切换到另一个任务去计算，当任务切回来的时候，恢复原来保存
的寄存器上下文和栈，从而可以迷惑操作系统，让其看到：该线程好像一直在计算，io比较少，从而会将更多的cpu执行权限分配给我们的程序
*/

func test() {
	for i := 0; i <= 10; i++ {
		fmt.Println("hello golang" + strconv.Itoa(i))
		//阻塞1秒
		time.Sleep(time.Second)
	}
}

func main() { //主线程

	go test() //go 方法名() 为该方法开启协程

	for i := 0; i <= 10; i++ {

		fmt.Println("hello msb" + strconv.Itoa(i))
		//阻塞一秒
		time.Sleep(time.Second)

	}

	//以上程序如果不开启协程的话
	//应该先将test方法中的for循环输出完之后，在输出main里的for循环，即使在test中的for循环阻塞了，也不会切换到main中的for循环

	//加了go之后表示开启协程，开启协程之后
	//程序开始-》go test()开启协程，执行协程中的代码，主线程代码继续执行，主线程结束之后，即使协程还没运行完，也会结束，也叫做主死从随

	//匿名函数+外部变量=闭包
	for i := 0; i <= 5; i++ {
		go func() {
			fmt.Println("for循环里的", i)
		}()

	} //开启多个协程，并不是顺序打印，是乱的
	time.Sleep(time.Second)
}
